package com.wt.admin.service.sys.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONUtil;
import com.aizuda.easy.security.code.BasicCode;
import com.aizuda.easy.security.properties.SecurityProperties;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wt.admin.code.sys.SysSettingCode;
import com.wt.admin.config.ConstVar;
import com.wt.admin.config.cache.Cache;
import com.wt.admin.domain.entity.sys.SysSettingEntity;
import com.wt.admin.mapper.sys.SysSettingMapper;
import com.wt.admin.service.sys.SysSettingService;
import com.wt.admin.util.AssertUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

@Service
public class SysSettingServiceImpl extends ServiceImpl<SysSettingMapper, SysSettingEntity> implements SysSettingService {

    @Resource
    private SysSettingMapper sysSettingMapper;
    @Resource
    private SecurityProperties securityProperties;
    @Resource
    private Cache<String, SysSettingEntity> settingCache;

    @Override
    public void init(){
        SysSettingEntity sysSettingEntity = find(null);
        settingCache.put(ConstVar.SettingModel.SETTING,sysSettingEntity);
    }

    @Override
    public SysSettingEntity find(SysSettingEntity data) {
        List<SysSettingEntity> sysSettingEntities = sysSettingMapper.find(data);
        AssertUtil.Boolean.isTrue(CollUtil.isEmpty(sysSettingEntities) || sysSettingEntities.size() > 1, BasicCode.BASIC_CODE_99998);
        SysSettingEntity sysSettingEntity = sysSettingEntities.get(0);
        if(ObjectUtil.isEmpty(sysSettingEntity.getUser())){
            sysSettingEntity.setUser(new SysSettingEntity.User());
        }
        if(ObjectUtil.isEmpty(sysSettingEntity.getApplication())){
            sysSettingEntity.setApplication(new SysSettingEntity.Application());
        }
        AES aes = SecureUtil.aes(securityProperties.getSecretKey().getBytes());
        sysSettingEntity.getUser().setPasswordInit(
                ObjectUtil.isEmpty(sysSettingEntity.getUser().getPasswordInit())? null: aes.decryptStr(sysSettingEntity.getUser().getPasswordInit())
        );
        return sysSettingEntity;
    }

    @Override
    public void edit(SysSettingEntity data) {
        checkUser(data);
        checkApplication(data);
        settingCache.put(ConstVar.SettingModel.SETTING,data);
        sysSettingMapper.updates(JSONUtil.toJsonStr(data.getUser()), JSONUtil.toJsonStr(data.getApplication()));
    }


    private void checkUser(SysSettingEntity data){
        SysSettingEntity.User user = data.getUser();
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(user), SysSettingCode.SETTING_CODE_1305);
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(user.getPasswordLength()) || user.getPasswordLength() < 6, SysSettingCode.SETTING_CODE_1300);
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(user.getPasswordInit()) || user.getPasswordInit().length() < 6, SysSettingCode.SETTING_CODE_1301);
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(user.getPasswordExpired()) || user.getPasswordExpired() < 1, SysSettingCode.SETTING_CODE_1302);
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(user.getTokenExpired()) || user.getTokenExpired() < 1, SysSettingCode.SETTING_CODE_1303);
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(user.getAccountLength()) || user.getAccountLength() < 5, SysSettingCode.SETTING_CODE_1309);
        // 对初始化密码校验规则
        check(data.getUser().getPasswordInit(), data.getUser());
        AES aes = SecureUtil.aes(securityProperties.getSecretKey().getBytes());
        user.setPasswordInit(aes.encryptHex(user.getPasswordInit()));
    }

    private void checkApplication(SysSettingEntity data){
        SysSettingEntity.Application application = data.getApplication();
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(application), SysSettingCode.SETTING_CODE_1310);
        AssertUtil.Boolean.isTrue(ObjectUtil.isEmpty(application.getOperationLogStored()) || application.getOperationLogStored() < 90, SysSettingCode.SETTING_CODE_1311);
    }

    // 检查字符串是否包含大写字母
    private static final String REGEX_UPPER = ".*[A-Z].*";
    // 检查字符串是否包含小写字母
    private static final String REGEX_LOWER = ".*[a-z].*";
    // 检查字符串是否包含特殊符号（非字母数字）
    private static final String REGEX_SPECIAL = ".*[`~!@#$%^&*()\\-=_+\\[\\]{};:'\"<>,.?/\\\\].*";
    Map<Integer, Consumer<String>> map = new HashMap<>(3){{
        put(0,(p) -> AssertUtil.Boolean.isFalse(p.matches(REGEX_UPPER), SysSettingCode.SETTING_CODE_1306));
        put(1,(p) -> AssertUtil.Boolean.isFalse(p.matches(REGEX_LOWER),SysSettingCode.SETTING_CODE_1307));
        put(2,(p) -> AssertUtil.Boolean.isFalse(p.matches(REGEX_SPECIAL),SysSettingCode.SETTING_CODE_1308));
    }};

    @Override
    public void check(String password,SysSettingEntity.User data){
        AssertUtil.Boolean.isTrue(password.length() < data.getPasswordLength(), SysSettingCode.SETTING_CODE_1304);
        for (int i = 0; i < data.getPasswordLever().size(); i++) {
            map.get(data.getPasswordLever().get(i)).accept(password);
        }
    }

}
